<!DOCTYPE html>
<html lang="zh">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
    <title>用户管理 - 学习二级域名分发系统</title>
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-touch-fullscreen" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="default">
    <link rel="stylesheet" type="text/css" href="/css/materialdesignicons.min.css">
    <link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
    <!--消息提示css-->
    <link rel="stylesheet" type="text/css" href="/css/animate.min.css">
    <!--表格插件css-->
    <link rel="stylesheet" href="/js/bootstrap-table/bootstrap-table.min.css">
    <!--日期选择器css-->
    <link rel="stylesheet" type="text/css" href="/js/bootstrap-datepicker/bootstrap-datepicker3.min.css">
    <!--时间日期选择器css-->
    <link rel="stylesheet" type="text/css" href="/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css">
    <!--对话插件css-->
    <link rel="stylesheet" type="text/css" href="/js/jquery-confirm/jquery-confirm.min.css">
    <link rel="stylesheet" type="text/css" href="/css/style.min.css">
</head>

<body>

    <div class="container-fluid">

        <div class="row">

            <div class="col-lg-12">
                <div class="card">
                    <header class="card-header">
                        <div class="card-title">用户列表</div>
                    </header>
                    <div class="card-body">
                        <div id="toolbar" class="toolbar-btn-action">
                            <button id="btn_add" type="button" class="btn btn-primary me-1">
                                <span class="mdi mdi-plus" aria-hidden="true"></span>新增
                            </button>
                        </div>
                        <table id="table"></table>

                    </div>
                </div>
            </div>

        </div>

    </div>
    <div class="modal fade" id="add" tabindex="-1" aria-labelledby="exampleModalLiveLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h6 class="modal-title" id="exampleModalLiveLabel">新增用户</h6>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="usernick_input" class="form-label">用户昵称</label>
                        <input type="text" class="form-control" id="usernick_input" placeholder="叫啥子" name="usernick">
                    </div>
                    <div class="mb-3">
                        <label for="username_input" class="form-label">用户名</label>
                        <input type="text" class="form-control" id="username_input" placeholder="abc?" name="username">
                    </div>
                    <div class="mb-3">
                        <label for="email_input" class="form-label">邮箱</label>
                        <input type="email" class="form-control" id="email_input" placeholder="xx@xx.xx" name="email">
                    </div>
                    <div class="mb-3">
                        <label for="password_input" class="form-label">密码</label>
                        <input type="password" class="form-control" id="password_input" placeholder="123321"
                            name="password">
                    </div>
                    <div class="mb-3">
                        <label for="domain_input" class="form-label">非备案域名数: 0</label>
                        <input type="range" class="form-range" min="0" max="10" id="domain_input" name="domain"
                            value="0">
                    </div>
                    <div class="mb-3">
                        <label for="record_input" class="form-label">备案域名数: 0</label>
                        <input type="range" class="form-range" min="0" max="5" id="record_input" name="record"
                            value="0">
                    </div>
                    <div class="mb-3">
                        <label for="auth_input" class="form-label">用户组</label>
                        <select class="form-select" aria-label="用户权限组" id="auth_input" name="auth">
                            <option selected value="null">请选择用户组</option>
                        </select>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                    <button type="submit" class="btn btn-primary">保存修改</button>
                </div>
            </div>
        </div>
    </div>

    <script type="text/javascript" src="/js/jquery.min.js"></script>
    <script type="text/javascript" src="/js/popper.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap.min.js"></script>
    <!--日期选择器js-->
    <script type="text/javascript" src="/js/bootstrap-datepicker/bootstrap-datepicker.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js"></script>

    <!--时间日期选择器js-->
    <script type="text/javascript" src="/js/momentjs/moment.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js"></script>
    <script type="text/javascript" src="/js/momentjs/locale/zh-cn.min.js"></script>
    <script type="text/javascript" src="/js/main.min.js"></script>
    <!--弹窗插件js-->
    <script type="text/javascript" src="/js/bootstrap-notify.min.js"></script>
    <!--加载插件js-->
    <script type="text/javascript" src="/js/lyear-loading.js"></script>
    <!--表格插件js-->
    <script src="/js/bootstrap-table/bootstrap-table.js"></script>
    <script src="/js/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
    <!--对话插件-->
    <script type="text/javascript" src="/js/jquery-confirm/jquery-confirm.min.js"></script>

    <script>
        $("input[name='domain']").on('input', function () {
            $("label[for='domain_input']").text("非备案域名数: " + $(this).val());
        });
        $("input[name='record']").on('input', function () {
            $("label[for='record_input']").text("备案域名数: " + $(this).val());
        });
        $("button[type='submit']").on('click', function () {
            var usernick = $("#usernick_input").val().trim();
            var username = $("#username_input").val().trim();
            var password = $("#password_input").val().trim();
            var email = $("#email_input").val().trim();
            var domain = $("#domain_input").val();
            var record = $("#record_input").val();
            var auth = $("#auth_input").val();
            if (usernick == "" || username == "" || password == "" || auth == "null") {
                return errify("请填写完整信息");
            }
            if (!validateEmail(email)) {
                return errify("请输入有效的邮箱地址");
            }

            function validateEmail(email) {
                // Regular expression for email validation
                var emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                return emailPattern.test(email);
            }

            $.ajax({
                url: "/admin/api",
                type: "POST",
                data: {
                    tag: "user",
                    act: "add",
                    usernick: usernick,
                    username: username,
                    password: password,
                    email: email,
                    domain: domain,
                    record: record,
                    auth: auth
                },
                success: function (data) {
                    if (data.code) {
                        $("#add").modal('hide');
                        $("#table").bootstrapTable('refresh');
                        $("usernick_input").val("");
                        $("username_input").val("");
                        $("password_input").val("");
                        $("email_input").val("");
                        $("domain_input").val(0);
                        $("record_input").val(0);
                        $("auth_input").val("");
                    } else {
                        errify(data.msg)
                    }
                },
                error: function () {
                    errify("网络错误");
                }
            });
        });
        var auth_arr;
        (() => {
            $.ajax({
                url: "/admin/api",
                type: "POST",
                data: {
                    tag: "user",
                    act: "auth"
                },
                success: function (data) {
                    var auth = data;
                    var html = "";
                    for (var i = 0; i < auth.length; i++) {
                        html += "<option value='" + auth[i].auth + "'>" + auth[i].name + "</option>";
                    }
                    $("#auth_input").append(html);
                    auth_arr = auth;
                },
                error: function () {
                    errify("网络错误");
                }
            });
        })()
        /**
         * 分页相关的配置
         **/
        const pagination = {
            // 分页方式：[client] 客户端分页，[server] 服务端分页
            sidePagination: "server",
            // 初始化加载第一页，默认第一页
            pageNumber: 1,
            // 每页的记录行数
            pageSize: 10,
            // 可供选择的每页的行数 - (亲测大于1000存在渲染问题)
            pageList: [5, 10, 25, 50, 100],
            // 在上百页的情况下体验较好 - 能够显示首尾页
            paginationLoop: true,
            // 展示首尾页的最小页数
            paginationPagesBySide: 2
        };

        /**
         * 按钮相关配置
         **/
        const button = {
            // 按钮的类
            buttonsClass: 'default',
            // 类名前缀
            buttonsPrefix: 'btn'
        }

        /**
         * 图标相关配置
         **/
        const icon = {
            // 图标前缀
            iconsPrefix: 'mdi',
            // 图标大小
            iconSize: 'mini',
            // 图标的设置
            icons: {
                columns: 'mdi-table-column-remove',
                paginationSwitchDown: 'mdi-door-closed',
                paginationSwitchUp: 'mdi-door-open',
                refresh: 'mdi-refresh',
                toggleOff: 'mdi-toggle-switch-off',
                toggleOn: 'mdi-toggle-switch',
                fullscreen: 'mdi-monitor-screenshot',
                detailOpen: 'mdi-plus',
                detailClose: 'mdi-minus'
            }
        };

        /**
         * 表格相关的配置
         **/
        const table = {
            classes: 'table table-bordered table-hover table-striped lyear-table',
            // 请求地址
            url: '/admin/api',
            // 唯一ID字段
            uniqueId: 'id',
            // 每行的唯一标识字段
            idField: 'id',
            // 是否启用点击选中行
            clickToSelect: true,
            // 是否显示详细视图和列表视图的切换按钮(clickToSelect同时设置为true时点击会报错)
            // showToggle: true,
            // 请求得到的数据类型
            dataType: 'json',
            // 请求方法
            method: 'post',
            // 工具按钮容器
            toolbar: '#toolbar',
            // 是否分页
            pagination: true,
            // 是否显示所有的列
            showColumns: true,
            // 是否显示刷新按钮
            showRefresh: true,
            // 显示图标
            showButtonIcons: true,
            // 显示文本
            showButtonText: false,
            // 显示全屏
            showFullscreen: true,
            // 开关控制分页
            showPaginationSwitch: true,
            // 总数字段
            totalField: 'total',
            // 当字段为 undefined 显示
            undefinedText: '-',
            // 排序方式
            sortOrder: "desc",
            ...icon,
            ...pagination,
            ...button
        };

        /**
         * 用于演示的列信息
         **/
        const columns = [{
            field: 'id',
            title: '编号',
            // 使用[align]，[halign]和[valign]选项来设置列和它们的标题的对齐方式。
            // h表示横向，v标识垂直
            align: 'center',
            // 是否作为排序列
            sortable: true,
            // visible: false,
            // 当列名称与实际名称不一致时可用
            // sortName: 'sortId',
            switchable: false,
            // 列的宽度
            width: 8,
            // 宽度单位
            widthUnit: 'rem',
            formatter: function (value, row, index) {
                return "<text onclick='xg.password(" + row.id + ")' data-bs-toggle=\"tooltip\" data-bs-placement=\"bottom\" title=\"单击修改密码\">" + value + "</text>";
            }
        }, {
            field: 'usernick',
            align: 'center',
            title: '昵称',
            formatter: function (value, row, index) {
                return "<text onclick='xg.usernick(" + row.id + ")'>" + value + "</text>";
            }
        }, {
            field: 'username',
            align: 'center',
            title: '用户名',
            titleTooltip: '注册用户名',
            formatter: function (value, row, index) {
                return "<text onclick='xg.username(" + row.id + ")'>" + value + "</text>";
            }
        }, {
            field: 'auth',
            align: 'center',
            title: '用户组',
            titleTooltip: '用户权限组',
            formatter: function (value, row, index) {
                return "<text onclick='xg.auth(" + row.id + ")'>" + value + "</text>";
            }
        }, {
            field: 'email',
            align: 'center',
            title: '邮箱',
            titleTooltip: '用户邮箱',
            formatter: function (value, row, index) {
                return "<text onclick='xg.email(" + row.id + ")'>" + value + "</text>";
            }
        }, {
            field: 'domain_num',
            align: 'center',
            title: '非备案域名数',
            titleTooltip: '给予的非备案域名数量',
            formatter: function (value, row, index) {
                return "<text onclick='xg.domain_num(" + row.id + "," + value + ")'>" + value + "</text>";
            }
        }, {
            field: 'record_num',
            align: 'center',
            title: '备案域名数',
            titleTooltip: '给予的备案域名数量',
            formatter: function (value, row, index) {
                return "<text onclick='xg.record_num(" + row.id + "," + value + ")'>" + value + "</text>";
            }
        }, {
            field: "update_time",
            align: "center",
            title: "登录时间",
            titleTooltip: "最后一次登录时间",
            sortable: true,
        }, {
            field: 'is_lock',
            title: '状态',
            formatter: function (value, row, index) {
                var value = "";
                if (row.is_lock == 1) {
                    value = '<span class="badge bg-light text-dark" data-bs-toggle="tooltip" data-bs-placement="bottom" title="单击修改" onclick="xg_lock(' + row.id + ',0)">禁用</span>';
                } else {
                    value = '<span class="badge bg-success" data-bs-toggle="tooltip" data-bs-placement="bottom" title="单击修改" onclick="xg_lock(' + row.id + ',1)">正常</span>';
                }
                return value;
            }
        }];
        //修改内容
        let xg = {
            password: (id) => {
                $.confirm({
                    title: '请输入新密码:',
                    content: '<div class="form-group p-1 mb-0">' +
                        '  <input autofocus="" type="text" id="input-pass" placeholder="新密码" class="form-control">' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = this.$content.find('input#input-pass');
                                if (!$.trim(input.val())) {
                                    errify("表单不完整")
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { password: input.val(), tag: "user", act: "xg_pass", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
            usernick: (id) => {
                $.confirm({
                    title: '请输入新昵称:',
                    content: '<div class="form-group p-1 mb-0">' +
                        '  <input autofocus="" type="text" id="input-nick" placeholder="新昵称" class="form-control">' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = this.$content.find('input#input-nick');
                                if (!$.trim(input.val())) {
                                    errify("表单不完整")
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { usernick: input.val(), tag: "user", act: "xg_nick", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
            username: (id) => {
                $.confirm({
                    title: '请输入新用户名:',
                    content: '<div class="form-group p-1 mb-0">' +
                        '  <input autofocus="" type="text" id="input-name" placeholder="新用户名" class="form-control">' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = this.$content.find('input#input-name');
                                if (!$.trim(input.val())) {
                                    errify("表单不完整")
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { username: input.val(), tag: "user", act: "xg_name", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
            auth: (id) => {
                $.confirm({
                    title: '请输入新用户组:',
                    content: '<div class="form-group p-1 mb-0">' +
                        '<select class="form-select" aria-label="新用户组" id="input-auth">' +
                        (() => {
                            var auth = auth_arr;
                            var html = "";
                            for (var i = 0; i < auth.length; i++) {
                                html += "<option value='" + auth[i].auth + "'>" + auth[i].name + "</option>";
                            }
                            return html;
                        })() +
                        '</select> ' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = this.$content.find('select#input-auth');
                                if (input.val() == null) {
                                    errify("表单不完整")
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { auth: input.val(), tag: "user", act: "xg_auth", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
            email: (id) => {
                $.confirm({
                    title: '请输入新邮箱:',
                    content: '<div class="form-group p-1 mb-0">' +
                        '  <input autofocus="" type="email" id="input-email" placeholder="新邮箱" class="form-control">' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = this.$content.find('input#input-email');
                                var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                                if (!emailRegex.test(input.val())) {
                                    errify("邮箱格式不正确");
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { email: input.val(), tag: "user", act: "xg_email", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
            domain_num: (id, value) => {
                $.confirm({
                    title: '请输入非备案域名数量:',
                    content: '<div class="input-group p-1 mb-0">' +
                        '<button class="btn btn-outline-secondary" type="button" id="button-addon1" onclick=\'xg_input("input#input-domain","down")\'> - </button>' +
                        '<input type="text" class="form-control" placeholder="" id="input-domain" aria-describedby="button-addon1" value="' + value + '" oninput="nums(this)">' +
                        '<button class="btn btn-outline-secondary" type="button" id="button-addon1" onclick=\'xg_input("input#input-domain","add")\'> + </button>' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = parseInt(this.$content.find('input#input-domain').val());
                                if (isNaN(input)) {
                                    errify("域名数量必须为数字");
                                    return false;
                                }
                                if (input < 0) {
                                    errify("域名数量不能小于0");
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { domain_num: input, tag: "user", act: "xg_domain", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
            record_num: (id, value) => {
                $.confirm({
                    title: '请输入备案域名数量:',
                    content: '<div class="input-group p-1 mb-0">' +
                        '<button class="btn btn-outline-secondary" type="button" id="button-addon1" onclick=\'xg_input("input#input-record","down")\'> - </button>' +
                        '<input type="text" class="form-control" placeholder="" id="input-record" aria-describedby="button-addon1" value="' + value + '" oninput="nums(this)">' +
                        '<button class="btn btn-outline-secondary" type="button" id="button-addon1" onclick=\'xg_input("input#input-record","add")\'> + </button>' +
                        '</div>',
                    buttons: {
                        sayMyName: {
                            text: '确定',
                            btnClass: 'btn-orange',
                            action: function () {
                                var input = parseInt(this.$content.find('input#input-record').val());
                                if (isNaN(input)) {
                                    errify("域名数量必须为数字");
                                    return false;
                                }
                                if (input < 0) {
                                    errify("域名数量不能小于0");
                                    return false;
                                } else {
                                    //发送修改请求
                                    $.post('/admin/api', { record_num: input, tag: "user", act: "xg_record", id: id }, function (data) {
                                        if (data.code == 200) {
                                            $.alert({
                                                content: data.msg,
                                                type: 'green'
                                            });
                                            $("#table").bootstrapTable('refresh');
                                        } else {
                                            errify(data.msg);
                                            return false;
                                        }
                                    })
                                }
                            }
                        },
                        '取消': function () { }
                    }
                });
            },
        }
        function nums(obj) {
            var num = $(obj).val();
            if (isNaN(num) || num < 0) {
                return $(obj).val(0);
            }
            $(obj).val($.trim(num));
        }
        function xg_input(id, tag) {
            var num = $(id).val();
            if (tag == "add") {
                var num = parseInt(num);
                if (!isNaN(num)) {
                    num += 1;
                } else {
                    num = 1;
                }
                $(id).val(num);
            } else {
                var num = parseInt(num);
                if (!isNaN(num)) {
                    num -= 1;
                } else {
                    num = 0;
                }
                if (num < 0) {
                    num = 0
                }
                $(id).val(num);
            }
        }
        // 自定义操作按钮
        function xg_lock(id, tg) {
            var l = $('body').lyearloading({
                opacity: 0.1,              // 遮罩层透明度，为0时不透明
                backgroundColor: '#ccc',           // 遮罩层背景色
                imgUrl: '',               // 使用图片时的图片地址
                textColorClass: 'text-success',   // 文本文字的颜色
                spinnerColorClass: 'text-success',   // 加载动画的颜色(不使用图片时有效)
                spinnerSize: 'lg',             // 加载动画的大小(不使用图片时有效，示例：sm/nm/md/lg，也可自定义大小，如：25px)
                spinnerText: '修改中...',       // 文本文字    
                zindex: 9999,             // 元素的堆叠顺序值
            });
            $.ajax({
                url: "/admin/api",
                type: "POST",
                data: {
                    tag: "user",
                    act: "xg_lock",
                    id: id,
                    is_lock: tg
                },
                success: function (data) {
                    l.hide();
                    if (data.code) {
                        $('table').bootstrapTable('refresh');
                    } else {
                        errify(data.msg)
                    }
                },
                error: function (data) {
                    l.hide();
                    errify("网络错误")
                }
            });
        }

        // 操作方法 - 编辑
        $("#btn_add").click(function () {
            $("#add").modal("show");
        });
        // 错误的弹窗
        function errify(msg) {
            $.notify({
                icon: 'mdi mdi-alert',
                message: msg
            }, {
                type: 'danger',
                allow_dismiss: true,
                newest_on_top: false,
                placement: {
                    from: 'top',
                    align: 'right'
                },
                offset: {
                    x: 20,
                    y: 20
                },
                spacing: 10,
                z_index: 9999,
                delay: 5000,
                animate: {
                    enter: 'animate__animated animate__fadeInDown',
                    exit: 'animate__animated animate__fadeOutUp'
                },
                onClosed: null,
                mouse_over: null
            });
        }

        $('table').bootstrapTable({
            ...table,
            // 自定义的查询参数
            queryParams: function (params) {
                return {
                    // 每页数据量
                    limit: params.limit,
                    // sql语句起始索引
                    offset: params.offset,
                    page: (params.offset / params.limit) + 1,
                    // 排序的列名
                    sort: params.sort,
                    // 排序方式 'asc' 'desc'
                    sortOrder: params.order,
                    tag: "user",
                    act: "list"
                };
            },
            columns,
            onLoadSuccess: function (data) {
                $("[data-bs-toggle='tooltip']").tooltip();
            }
        });
    </script>
</body>

</html>